package com.browsesoft.excel;

import java.io.File;
import java.io.FileOutputStream;
import java.util.Enumeration;
import java.util.LinkedList;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.Region;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Text;

import com.browsesoft.ExtendElement;
import com.browsesoft.PropertiesService;
import com.browsesoft.Tools;
import com.browsesoft.htmlcomponent.HTMLBasicComponent;
import com.browsesoft.user.User;

/**
 * <p>
 * Title:把数据导出到Excel
 * </p>
 * <p>
 * 最后修改时间:2004.10.9
 * </p>
 * <p>
 * Copyright: Copyright (c) 2004
 * </p>
 * <p>
 * Company:browse star
 * </p>
 * 
 * @author hehuaxun
 * @version 1.0
 */
public class ExcelComponent extends HTMLBasicComponent {
	public ExcelComponent(HTMLBasicComponent parent) throws Exception {
		super(parent);
	}

	/**
	 * 初始化时创建子组件并设置初始化参数
	 */
	public void init(HttpServletRequest request, Element e) throws Exception {
		super.init(request, e);
		if (!ExtendElement.findElements(e, "pages", "pages").isEmpty()) {
			// 获得元素 pages="pages"
			Element ee = (Element) ExtendElement.findElements(e, "pages",
					"pages").getFirst();
			// 定义参数parameter 用来替换
			String excelparam = "";
			// 定义变量onclick保存 onclick的值
			String onclick = ee.getAttribute("onclick");
			// 获得属性 pages的值
			String pages = ee.getAttribute("pages");
			if (pages != null && !pages.equals("")) {
				// 如果是分页显示，但是需要导出所有数据
				if (pages.equals("pages")) {
					Enumeration paramNames = request.getParameterNames();
					while (paramNames.hasMoreElements()) {
						Object key = paramNames.nextElement();
						String paramName = key.toString();
						String paramValue = request.getParameter(paramName);
						if (!paramName.equals("templatename")) {
							excelparam = excelparam + "&" + paramName + "="
									+ paramValue;
						}
					}
					if (excelparam.equals("")) {
						onclick = onclick.replaceAll("#excelparam#", " ");
					} else {
						onclick = onclick
								.replaceAll("#excelparam#", excelparam);
					}
				} // end 如果是分页显示
			}
		}
	}

	/**
	 * 处理用户请求，将需要Model处理的内容提交给Model
	 * 
	 * @param request
	 *            客户端请求
	 */
	public void service(HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		super.service(request, response);
		// 获得参数
		String filename = request.getParameter("excelfilename");
		String action = request.getParameter("action");
		// 获得用户
		User user = (User) request.getSession().getAttribute("loginUser");
		// 获得根目录
		String filepath = null;
		// 从属性文件中获得excel的保存文件
		String rootPath = PropertiesService.getProperty("excel", "path");
		if (action != null && action.equals("excel")) {
			if (filename != null && !filename.equals("")) {
				// 获得完整的文件名
				if (filename.toLowerCase().endsWith(".xls")) {
					filepath = rootPath + filename;
				} else {
					filepath = rootPath + filename + ".xls";
					filename = filename + ".xls";
				}
				// 创建一个Excel文件
				File file = new File(filepath);
				if (file.exists()) {
					this.getPage()
							.showMessage("alert('文件已经存在');window.close()");
					return;
				}
				// 导出所有数据
				getSheet(file, this.getPage().getDocument());
				// 在数据库中填加维护记录
				ExcelEntity entity = new ExcelEntity();
				entity.getAttributes().put("entitytype", "excelfile");
				entity.getAttributes().put("tablename", "t_excelfile");
				entity.getAttributes().put("parentid", "");
				entity.getAttributes().put("filename", filename);
				entity.getAttributes().put("username", user.getName());
				entity.getAttributes()
						.put("createtime", Tools.getDateOfToday());
				entity.getAttributes().put("filepath", filepath);
				entity.insert();
			}
		}
	}

	/**
	 * 把页面数据导出到Excel 传递一个document 并把结果到入到Excel
	 */
	public void getSheet(File file, Document doc) {
		try {
			// 判断是否需要分页导出数据
			Element node_body = (Element) doc.getElementsByTagName("body")
					.item(0);
			if (!ExtendElement.findElements((Element) node_body, "excel",
					"excel").isEmpty()) {
				Element node_excel = (Element) ExtendElement.findElements(
						(Element) node_body, "excel", "excel").getFirst();
				if (node_excel.getAttribute("sheet").equals("sheets")) {
					// 写文件 每一个的table的数据 导出到一个sheet上
					writeExcelByDocforPage(file, doc);
				} else {
					// 写文件 所有的数据导出到一个sheet上
					writeExcelByDoc(file, doc);
				}
			} else {
				// 写文件 所有的数据导出到一个sheet上
				writeExcelByDoc(file, doc);
			}
			// 读文件
			// readExcel(file);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * *把数组数据导出到Excel
	 * 
	 * @param filename
	 *            Excel文件名
	 * @param title
	 *            表名
	 * @param header
	 *            表头
	 * @param footer
	 *            表尾
	 * @param datas
	 *            二维数组保存数据 第一行应该是字段名称
	 */
	public void getSheet(String filename, String title, String header,
			String footer, String datas[][]) {
		try {
			// 创建一个Excel文件
			String rootPath = Tools.getAbsolutePath();
			rootPath = rootPath.substring(0, rootPath.length() - 1);
			if (filename.toLowerCase().endsWith(".xls")) {
				filename = rootPath + "excel\\" + filename;
			} else {
				filename = rootPath + "excel\\" + filename + ".xls";
			}
			File file = new File(filename);
			if (file.exists()) {
				this.getPage().showMessage("文件已经存在！");
				return;
			}
			// 写文件
			writeExcel(file, title, header, footer, datas);
			// 读文件
			// readExcel(file);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 把二维数组的数据导出到Excel
	 * 
	 * @param file
	 *            文件名称
	 * @param datas
	 *            二维数组保存数据
	 * @throws Exception
	 */
	public static void writeExcel(File file, String title, String header,
			String footer, String datas[][]) throws Exception {
		// 创建一个工作薄
		HSSFWorkbook workbook = new HSSFWorkbook();
		FileOutputStream fileOutputStream = new FileOutputStream(file);
		// 创建新的一页
		HSSFSheet sheet = workbook.createSheet();
		// 定义行和列
		HSSFRow row = null;
		HSSFCell cell = null;
		// 设置字体
		HSSFFont font = workbook.createFont();
		font.setColor((short) HSSFFont.COLOR_NORMAL);
		font.setBoldweight((short) HSSFFont.BOLDWEIGHT_BOLD);
		// 设置格式
		HSSFCellStyle cellStyle = workbook.createCellStyle();
		cellStyle.setAlignment((short) HSSFCellStyle.ALIGN_CENTER);
		cellStyle.setFont(font);
		// 创建第0行 标题
		row = sheet.createRow((short) 0);
		cell = row.createCell((short) 0);
		cell.setCellValue(title);
		cell.setCellStyle(cellStyle);
		// 创建第1行
		row = sheet.createRow((short) 1);
		// 创建第2行 header
		row = sheet.createRow((short) 2);
		cell = row.createCell((short) 0);
		cell.setCellValue(header);
		cell.setCellStyle(cellStyle);
		// 定义列数
		int colNumber = 0;
		colNumber = datas[0].length;
		// 定义合并区域
		Region reg = new Region(0, (short) 0, 0, (short) (colNumber - 1));
		sheet.addMergedRegion(reg);
		reg = new Region(1, (short) 0, 1, (short) (colNumber - 1));
		sheet.addMergedRegion(reg);
		reg = new Region(2, (short) 0, 2, (short) (colNumber - 1));
		sheet.addMergedRegion(reg);
		// 从数组中取数 填写内容
		for (int r = 0; r < datas.length; r++) {
			// 创建行
			row = sheet.createRow((short) r + 3);
			for (int c = 0; c < datas[r].length; c++) {
				// 创建列
				cell = row.createCell((short) c);
				// 设置列类型
				cell.setCellType(HSSFCell.CELL_TYPE_STRING);
				// 设置列的字符集为中文
				cell.setEncoding((short) HSSFCell.ENCODING_UTF_16);
				// 设置内容
				cell.setCellValue(datas[r][c]);
			}
		}
		// 填加表尾 footer
		row = sheet.createRow((short) (datas.length + 2));
		cell = row.createCell((short) 0);
		cell.setCellValue(footer);
		cell.setCellStyle(cellStyle);
		reg = new Region((datas.length + 4), (short) 0, (datas.length + 4),
				(short) (colNumber - 1));
		sheet.addMergedRegion(reg);
		// 写文件
		workbook.write(fileOutputStream);
		// 清缓存
		fileOutputStream.flush();
		// 关闭文件流
		fileOutputStream.close();
	}

	/**
	 * 读文件
	 * 
	 * @param file
	 *            文件
	 * @throws Exception
	 */
	public static void readExcel(File file) throws Exception {
	}

	/**
	 * 获得最大的行数
	 * 
	 */
	public int getRowNumber(Element e) throws Exception {
		int result = 0;
		int row = 0;
		for (int i = 0; i < e.getChildNodes().getLength(); i++) {
			Node ee = e.getChildNodes().item(i);
			if (ee.getNodeName().equals("tr")) {
				row++;
			}
		}
		result = row;
		return result;
	}

	/**
	 * 获得某一节点下最大的列数
	 * 
	 */
	public int getColNumber(Element e) throws Exception {
		int result = 0;
		int tcol = 0;
		int col = 0;
		for (int i = 0; i < e.getChildNodes().getLength(); i++) {
			Node ee = e.getChildNodes().item(i);
			if (ee.getNodeName().equals("tr")) {
				for (int j = 0; j < ee.getChildNodes().getLength(); j++) {
					Node td = ee.getChildNodes().item(j);
					// 获得表单的每一行的每一单元格
					if (td.getNodeName().equals("td")) {
						tcol++;
					}
				}
				if (tcol > col) {
					col = tcol;
				}
				tcol = 0;
			}
		}
		result = col;
		return result;
	}

	/**
	 * 获得某一行中不在合并区域的有效列数
	 * 
	 */
	public int getValidcol(LinkedList lk, int rowNumber, int colNumber) {
		int n = 0;
		Region reg = null;
		// 循环判断（rowNumber,colNumber）是否在合并的区域内部
		for (int i = 0; i < lk.size(); i++) {
			reg = (Region) lk.get(i);
			if (reg.contains(rowNumber, (short) colNumber)) {
				colNumber++;
			} else {
				n++;
			}
		}
		if (n < lk.size()) {
			colNumber = getValidcol(lk, rowNumber, colNumber);
		}
		return colNumber;
	}

	/**
	 * 获得Select选择框的内容
	 * 
	 */
	public String getSelectContent(Node n) {
		String result = null;
		Element nn = (Element) ExtendElement.findElements((Element) n,
				"selected", "selected").getFirst();
		Node m = nn.getFirstChild();
		if (m.getNodeType() == Node.TEXT_NODE) {
			result = ((Text) m).getNodeValue();
		} else {
			result = "";
		}
		return result;
	}

	/**
	 * 获得textarea 文本区域的内容
	 * 
	 */
	public String getTextareaContent(Node n) {
		String result = null;
		Node m = n.getFirstChild();
		if (m.getNodeType() == Node.TEXT_NODE) {
			result = ((Text) m).getNodeValue();
		} else {
			result = "";
		}
		return result;
	}

	/**
	 * 获得div的内容
	 * 
	 */
	public String getDivContent(Node n) {
		String result = null;
		Node m = n.getFirstChild();
		if (m.getNodeType() == Node.TEXT_NODE) {
			result = ((Text) m).getNodeValue();
		} else {
			result = "";
		}
		return result;
	}

	/**
	 * 把页面数据导出到Excel 所有数据导出到一个sheet中
	 * 
	 * @param file
	 *            文件名称
	 * @param doc
	 *            页面参数
	 * @throws Exception
	 */
	public void writeExcelByDoc(File file, Document doc) throws Exception {
		// Node root=doc.getElementsByTagName("table").item(0);
		// 创建一个工作薄
		HSSFWorkbook workbook = new HSSFWorkbook();
		FileOutputStream fileOutputStream = new FileOutputStream(file);
		// 创建新的一页
		HSSFSheet sheet = workbook.createSheet();
		// 定义行和列
		HSSFRow row = null;
		HSSFCell cell = null;
		// 定义行号r 用来保存当前是第几行
		int rowNumber = -1;
		// 定义列号c 用来保存当前是第几列
		int colNumber = -1;
		// 定义合并的行数
		int rowspan = 0;
		// 定义合并的行数
		int colspan = 0;
		// 定义合并域的likedlist
		LinkedList mergerAreas = new LinkedList();
		// 定义一个合并区域
		Region reg = null;
		// 定义表节点（元素）
		Element e_table = null;
		// 获得导出的位置
		Element node_body = (Element) doc.getElementsByTagName("body").item(0);
		Element node_excel = (Element) ExtendElement.findElements(
				(Element) node_body, "excel", "excel").getFirst();
		// e_table =(Element) node_excel.getElementsByTagName("table").item(0);
		// //获得最大的行数和最大的列数
		// int maxRowNum = getRowNumber(e_table);
		// int maxColNum = getColNumber(e_table);
		// //定义合并区域
		// reg = new Region(0, (short) 0, 0, (short) (maxColNum - 1));
		// sheet.addMergedRegion(reg);
		// //创建第1行
		// row = sheet.createRow( (short) 1);
		// 查看文挡(doc)里面有几个table 每一个table进行循环
		for (int n = 0; n < node_excel.getElementsByTagName("table")
				.getLength(); n++) {
			// 获得每一个table元素
			e_table = (Element) node_excel.getElementsByTagName("table")
					.item(n);
			for (int i = 0; i < e_table.getElementsByTagName("tr").getLength(); i++) {
				Element node_tr = (Element) e_table.getElementsByTagName("tr")
						.item(i);
				// 获得表单的每一行
				if (node_tr.getNodeName().equals("tr")) {
					rowNumber++;
					// 创建第rowNumber行
					row = sheet.createRow((short) (rowNumber));
					colNumber = -1;
					for (int j = 0; j < node_tr.getElementsByTagName("td")
							.getLength(); j++) {
						Node node_td = node_tr.getElementsByTagName("td").item(
								j);
						// 获得表单的每一行的每一单元格
						if (node_td.getNodeName().equals("td")) {
							colNumber++;
							// 获得合并的行数
							String tmp = null;
							tmp = ((Element) node_td).getAttribute("rowspan");
							if (tmp != null && !tmp.equals("")) {
								rowspan = Integer.parseInt(tmp) - 1;
							} else {
								rowspan = 0;
							}
							// 获得合并的列数
							tmp = ((Element) node_td).getAttribute("colspan");
							if (tmp != null && !tmp.equals("")) {
								colspan = Integer.parseInt(tmp) - 1;
							} else {
								colspan = 0;
							}
							// 创建合并区域
							if (rowspan > 0 || colspan > 0) {
								// 创建列
								cell = row.createCell((short) colNumber);
								// 设置列类型
								cell.setCellType(HSSFCell.CELL_TYPE_STRING);
								// 设置列的字符集为中文
								cell
										.setEncoding((short) HSSFCell.ENCODING_UTF_16);
								// 设置内容
								// cell.setCellValue("hello");
								// 创建合并区域
								reg = new Region(rowNumber, (short) colNumber,
										(rowNumber + rowspan),
										(short) (colNumber + colspan));
								// 在mergerAeeans中添加合并区域
								mergerAreas.add(reg);
								// 在Sheet中创建合并区域
								sheet.addMergedRegion(reg);
							} else {
								// 寻找不在合并区域的列号
								colNumber = getValidcol(mergerAreas, rowNumber,
										colNumber);
								// 创建列
								cell = row.createCell((short) colNumber);
								// 设置列类型
								cell.setCellType(HSSFCell.CELL_TYPE_STRING);
								// 设置列的字符集为中文
								cell
										.setEncoding((short) HSSFCell.ENCODING_UTF_16);
								// 设置内容
								// cell.setCellValue("hello");
							}
							Node td1 = node_td.getChildNodes().item(0);
							LinkedList lk = ExtendElement
									.findElementContext(node_td);
							if (lk.size() > 0
									&& !((Text) lk.get(0)).getNodeValue()
											.trim().equals("")) {
								String content = ((Text) lk.get(0))
										.getNodeValue().trim();
								// 设置内容
								cell.setCellValue(content);
							} else {
								// 如果是元素
								if (td1 instanceof Element) {
									Element c2 = (Element) node_td
											.getFirstChild();
									// 如果是Input 文本输入框
									if (c2.getNodeName().equals("input")) {
										// 设置内容
										cell.setCellValue(c2
												.getAttribute("value"));
									}
									// 如果是Select 文本选择框
									else if (c2.getNodeName().equals("select")) {
										// 设置内容
										cell.setCellValue(getSelectContent(c2));
									}
									// 如果是div
									else if (c2.getNodeName().equals("div")) {
										// 设置内容
										cell.setCellValue(getDivContent(c2));
									}
								}
								// 如果是其他
								else {
									// 设置内容
									cell.setCellValue("");
								}
							}
						}
					}
				}
			} // end for table
		} // end for doc
		// 写文件
		workbook.write(fileOutputStream);
		// 清缓存
		fileOutputStream.flush();
		// 关闭文件流
		fileOutputStream.close();
	}

	/**
	 * 把页面数据导出到Excel 每个table的数据导出到一个sheet中
	 * 
	 * @param file
	 *            文件名称
	 * @param doc
	 *            页面参数
	 * @throws Exception
	 */
	public void writeExcelByDocforPage(File file, Document doc)
			throws Exception {
		// 创建一个工作薄
		HSSFWorkbook workbook = new HSSFWorkbook();
		FileOutputStream fileOutputStream = new FileOutputStream(file);
		// 定义一页
		HSSFSheet sheet = null;
		// 定义行和列
		HSSFRow row = null;
		HSSFCell cell = null;
		// 定义行号r 用来保存当前是第几行
		int rowNumber = -1;
		// 定义列号c 用来保存当前是第几列
		int colNumber = -1;
		// 定义合并的行数
		int rowspan = 0;
		// 定义合并的行数
		int colspan = 0;
		// 定义合并域的likedlist
		LinkedList mergerAreas = new LinkedList();
		// 定义一个合并区域
		Region reg = null;
		// 定义表节点（元素）
		Element e_table = null;
		// 获得导出的位置
		Element node_body = (Element) doc.getElementsByTagName("body").item(0);
		Element node_excel = (Element) ExtendElement.findElements(
				(Element) node_body, "excel", "excel").getFirst();
		// 查看文挡(doc)里面有几个table 每一个table进行循环
		for (int n = 0; n < node_excel.getElementsByTagName("table")
				.getLength(); n++) {
			// 获得每一个table元素
			e_table = (Element) node_excel.getElementsByTagName("table")
					.item(n);
			// 创建一个新页面
			sheet = workbook.createSheet();
			// 清空合并区域的内容
			mergerAreas.clear();
			// 重新设置行号
			rowNumber = -1;
			for (int i = 0; i < e_table.getChildNodes().getLength(); i++) {
				Node node_tr = e_table.getChildNodes().item(i);
				// 获得表单的每一行
				if (node_tr.getNodeName().equals("tr")) {
					rowNumber++;
					// 创建第rowNumber行
					row = sheet.createRow((short) (rowNumber));
					colNumber = -1;
					for (int j = 0; j < node_tr.getChildNodes().getLength(); j++) {
						Node node_td = node_tr.getChildNodes().item(j);
						// 获得表单的每一行的每一单元格
						if (node_td.getNodeName().equals("td")) {
							colNumber++;
							// 获得合并的行数
							String tmp = null;
							tmp = ((Element) node_td).getAttribute("rowspan");
							if (tmp != null && !tmp.equals("")) {
								rowspan = Integer.parseInt(tmp) - 1;
							} else {
								rowspan = 0;
							}
							// 获得合并的列数
							tmp = ((Element) node_td).getAttribute("colspan");
							if (tmp != null && !tmp.equals("")) {
								colspan = Integer.parseInt(tmp) - 1;
							} else {
								colspan = 0;
							}
							// 创建合并区域
							if (rowspan > 0 || colspan > 0) {
								// 创建列
								cell = row.createCell((short) colNumber);
								// 设置列类型
								cell.setCellType(HSSFCell.CELL_TYPE_STRING);
								// 设置列的字符集为中文
								cell
										.setEncoding((short) HSSFCell.ENCODING_UTF_16);
								// 设置内容
								// cell.setCellValue("hello");
								// 创建合并区域
								reg = new Region(rowNumber, (short) colNumber,
										(rowNumber + rowspan),
										(short) (colNumber + colspan));
								// 在mergerAeeans中添加合并区域
								mergerAreas.add(reg);
								// 在Sheet中创建合并区域
								sheet.addMergedRegion(reg);
							} else {
								// 寻找不在合并区域的列号
								colNumber = getValidcol(mergerAreas, rowNumber,
										colNumber);
								// 创建列
								cell = row.createCell((short) colNumber);
								// 设置列类型
								cell.setCellType(HSSFCell.CELL_TYPE_STRING);
								// 设置列的字符集为中文
								cell
										.setEncoding((short) HSSFCell.ENCODING_UTF_16);
								// 设置内容
								// cell.setCellValue("hello");
							}
							Node td1 = node_td.getChildNodes().item(0);
							// 如果是元素
							if (td1 instanceof Element) {
								Element c2 = (Element) node_td.getFirstChild();
								// 如果是Input 文本输入框
								if (c2.getNodeName().equals("input")) {
									// 设置内容
									cell.setCellValue(c2.getAttribute("value"));
								}
								// 如果是Select 文本选择框
								else if (c2.getNodeName().equals("select")) {
									// 设置内容
									cell.setCellValue(getSelectContent(c2));
								}
								// 如果是textarea文本选择框
								else if (c2.getNodeName().equals("textarea")) {
									// 设置内容
									cell.setCellValue(getTextareaContent(c2));
								}
								// 如果是div
								else if (c2.getNodeName().equals("div")) {
									// 设置内容
									cell.setCellValue(getDivContent(c2));
								}
							}
							// 如果是文本
							else if (td1 instanceof Text) {
								// 设置内容
								cell.setCellValue(((Text) td1).getNodeValue());
							}
							// 如果是其他
							else {
								// 设置内容
								cell.setCellValue("");
							}
						}
					}
				}
			} // end for table
		} // end for doc
		// 写文件
		workbook.write(fileOutputStream);
		// 清缓存
		fileOutputStream.flush();
		// 关闭文件流
		fileOutputStream.close();
	}
}
